#include "MainWindow.h"
#include <QtGlobal>
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>


MainWindow::MainWindow(QWidget* parent):
    QMainWindow(parent), pixelZoom(4)
{
    ui.setupUi(this);

    wireframe = false;
    rasterize = true;
    ui.actionWireFrame->setChecked(false);
    ui.actionPreencher->setChecked(true);

    connect(ui.actionWireFrame, SIGNAL(toggled(bool)), this, SLOT(wireframeClicked(bool)));
    connect(ui.actionPreencher, SIGNAL(toggled(bool)), this, SLOT(rasterizeClicked(bool)));
    connect(ui.addTriangleButton, SIGNAL(pressed()), this, SLOT(adicionarTriangulo()));

    paint();


}

void MainWindow::paint(){

    buffer = QImage(ui.imageContainer->size(), QImage::Format_RGB32);
    buffer.fill(qRgb(255, 255, 255));


    /* "Unit Tests" */
//    drawLine1(QPoint(50, 70), QPoint(90, 70));
//    drawLine1(QPoint(50, 130), QPoint(90, 80));
//    drawLine1(QPoint(40, 70), QPoint(50, 100));
//    drawLine1(QPoint(90, 70), QPoint(50, 80));
//    drawLine1(QPoint(50, 100), QPoint(40, 70));
//    drawLine1(QPoint(50, 70), QPoint(50, 80));

//    drawLine2(QPoint(50, 70), QPoint(90, 70));
//    drawLine2(QPoint(50, 70), QPoint(90, 80));
//    drawLine2(QPoint(40, 70), QPoint(50, 100));
//    drawLine2(QPoint(90, 70), QPoint(50, 80));
//    drawLine2(QPoint(50, 100), QPoint(40, 70));
//    drawLine2(QPoint(50, 70), QPoint(50, 80));


    QColor cor(0, 0, 255);


    for (int i = 0; i<triangulos.size(); i++) {

        Triangle t = triangulos.at(i);
        drawTriangle(t.getV1(),
                     t.getV2(),
                     t.getV3(),
                     t.cor);
    }

    ui.imageContainer->setPixmap(QPixmap::fromImage(buffer));

}


void MainWindow::putPixel(const QPoint& point, const QColor& color)
{
    QPainter painter(&buffer);
    painter.fillRect(point.x() * pixelZoom, point.y() * pixelZoom, pixelZoom, pixelZoom, color);
}

void MainWindow::drawLine(const QPoint &point1, const QPoint &point2, const QColor &color) {

    if (point1 == point2) {
        putPixel(point1, color);
        return;
    }

    QPoint p1 = point1;
    QPoint p2 = point2;

    int dx = p2.x() - p1.x();
    int dy = p2.y() - p1.y();

    if (qAbs(dx) < qAbs(dy)) {

        double m = (double)dx / (double)dy;
        double b = point1.x() - point1.y() * m;

        if(point2.y() < point1.y())
        {
            p1 = point2;
            p2 = point1;
        }

        for(int y = p1.y(); y <= p2.y(); y++)
        {
            int x = m * y + b;
            QPoint p(x, y);
            putPixel(p, color);
        }

    }
    else {

        if(point2.x() < point1.x())
        {
            p1 = point2;
            p2 = point1;
        }

        double m = (double)dy / (double)dx;
        double b = point1.y() - point1.x() * m;

        for (int x = p1.x(); x <= p2.x(); x++)
        {
            int y = m * x + b;
            QPoint p(x, y);
            putPixel(p, color);
        }

    }

}

void MainWindow::drawTriangle( const QPoint point1, const QPoint point2, const QPoint point3, const QColor &color)
{

    if(rasterize){
        QPoint p1;
        QPoint p2;
        QPoint p3;
        if ( point1.x() <= point2.x() && point1.x() <= point3.x()){
            p1 = point1;
            if ( point2.x() <= point3.x()){
                p2 = point2;
                p3 = point3;
            } else{
                p3 = point2;
                p2 = point3;
            }
        } else if ( point2.x() <= point1.x() && point2.x() <= point3.x()){
                    p1 = point2;
                    if ( point1.x() <= point3.x()){
                        p2 = point1;
                        p3 = point3;
                    } else{
                        p3 = point1;
                        p2 = point3;
                    }
        } else if ( point3.x() <= point2.x() && point3.x() <= point1.x()){
            p1 = point3;
            if ( point1.x() <= point2.x()){
                p2 = point1;
                p3 = point2;
            } else{
                p3 = point1;
                p2 = point2;
            }
        }
        qDebug("p1 = (%d,%d)",p1.x(),p1.y());
        qDebug("p2 = (%d,%d)",p2.x(),p2.y());
        qDebug("p3 = (%d,%d)",p3.x(),p3.y());

        int dx12 = p2.x() - p1.x();
        int dy12 = p2.y() - p1.y();

        int dx13 = p3.x() - p1.x();
        int dy13 = p3.y() - p1.y();

        int dx23 = p3.x() - p2.x();
        int dy23 = p3.y() - p2.y();

        double m12 = (double)dy12 / (double)dx12;
        double b12 = p1.y() - m12 * p1.x();

        double m13 = (double)dy13 / (double)dx13;
        double b13 = p1.y() - m13 * p1.x();

        double m23 = (double)dy23 / (double)dx23;
        double b23 = p2.y() - m23 * p2.x();

        qDebug("m12 b12 = (%f,%f)",m12,b12);
        qDebug("m13 b13 = (%f,%f)",m13,b13);
        qDebug("m23 b23 = (%f,%f)",m23,b23);

        drawHalfTriangle(p1.x(), p2.x(), m12, m13, b12, b13, color);
        drawHalfTriangle(p2.x(), p3.x(), m23, m13, b23, b13, color);
    }

    QColor cor = color;
    if (wireframe)  {
        cor.setRed( (color.red()+30)%255);
        cor.setGreen( (color.green()+30)%255);
        cor.setBlue( (color.blue()+30)%255);

    }
    if(wireframe || rasterize){
        drawLine(point1,point2,cor);
        drawLine(point1,point3,cor);
        drawLine(point2,point3,cor);
    }
}

void MainWindow::drawHalfTriangle(int x0, int xf, double m1, double m2, double b1, double b2, const QColor& color){

    if(x0 < xf){
        for (int x = x0; x < xf; x++)
        {
            int y1 = m1 * x + b1;
            int y2 = m2 * x + b2;

            QPoint p1(x, y1);
            QPoint p2(x, y2);

            drawLine(p1, p2, color);
        }
    }
}

void MainWindow::wireframeClicked(bool wireFrame)
{
    this->wireframe = wireFrame;

    qDebug("wireframe "+wireFrame);

    paint();
}

void MainWindow::rasterizeClicked(bool preencher)
{
    this->rasterize = preencher;
    paint();
    qDebug("rasterize "+rasterize);
}

void MainWindow::adicionarTriangulo(){
    QPoint p1( ui.trianguloX1->value(), ui.trianguloY1->value() );
    QPoint p2( ui.trianguloX2->value(), ui.trianguloY2->value() );
    QPoint p3( ui.trianguloX3->value(), ui.trianguloY3->value() );
    QColor c(ui.corR->value(),ui.corG->value(),ui.corB->value());

    triangulos.append(Triangle(p1,p2,p3,c));

    qDebug()<<"Triangulos adicionados \n";
    qDebug("p1 = (%d,%d)",p1.x(),p1.y());
    qDebug("p2 = (%d,%d)",p2.x(),p2.y());
    qDebug("p3 = (%d,%d)",p3.x(),p3.y());

    paint();
}






